
#include "GlobalManager.h"
#include <fstream>
#include <iostream>
#include <algorithm>
#include <stdexcept>
#include "../3rd/filesystem/include/ghc/filesystem.hpp"
#include "GlobalManager.h"

std::string formatPath(const std::string& basePath, const std::string& fileName) {
	ghc::filesystem::path path = ghc::filesystem::path(basePath) / fileName;
	std::string formattedPath = path.string();
	std::replace(formattedPath.begin(), formattedPath.end(), '\\', '/');
	return formattedPath;
}

int CGlobalManager::replace_all(std::string& strBuf, std::string strSrc, std::string strDes) {
	if (strSrc.empty()) {
		return 0;  // 无需替换，返回替换次数为0
	}
	std::size_t pos = 0;
	int nCount = 0;
	while ((pos = strBuf.find(strSrc, pos)) != std::string::npos) {
		strBuf.replace(pos, strSrc.length(), strDes);
		pos += strDes.length();
		++nCount;
	}
	return nCount;
}

CGlobalManager::CGlobalManager() : ini(std::make_unique<CSimpleIniA>()) {

	m_encoder_name = "libx264";
	m_decoder_name = "libx264";
	loadConfig("config.ini");
}

CGlobalManager& CGlobalManager::getInstance() {
	static CGlobalManager instance;
	return instance;
}

bool CGlobalManager::loadConfig(const std::string& filename) {
	SI_Error rc = ini->LoadFile(filename.c_str());
	if (rc < 0) {
		std::cerr << "Failed to load config file: " << filename << " with error code: " << rc << std::endl;
		return false;
	}
	m_maplabels.clear();
	loadConfigValues();
	return true;
}

bool CGlobalManager::Init(const std::string& enginePath, const std::string& engineFile, const std::string& labelFile)
{
	
	// 读取 [tensort] 配置项
	m_engine_path = enginePath;
	m_engine_file = engineFile;
	m_label_file = labelFile;

	// 使用std::filesystem处理label_file路径
	ghc::filesystem::path labelFilePath = ghc::filesystem::path(m_engine_path) / m_label_file;
	m_label_file = labelFilePath.string();

	// 替换路径中的反斜杠
	replace_all(m_label_file, "\\", "/");

	// 打开label文件并读取内容
	std::ifstream f(m_label_file);
	if (f.is_open()) 
	{
		m_maplabels.clear();
		std::string name;
		int i = 0;
		while (std::getline(f, name)) {
			m_maplabels[i++] = name;
		}
		return true;		
	}
	else
	{
		return false;
	}

}

void CGlobalManager::loadConfigValues() {
	// 读取 [darknetPlay] 配置项
	out_width = std::stoi(ini->GetValue("darknetPlay", "out_width", "0"));
	out_height = std::stoi(ini->GetValue("darknetPlay", "out_height", "0"));
	sleeptime = std::stoi(ini->GetValue("darknetPlay", "sleeptime", "50"));
	yolo_version = ini->GetValue("darknetPlay", "yolo_version", "V8");

	// 读取 [torch] 配置项
	weights_path = ini->GetValue("torch", "weights_path", "");
	weights_file = ini->GetValue("torch", "weights_file", "");
	class_path = ini->GetValue("torch", "class_path", "");
	class_file = ini->GetValue("torch", "class_file", "");

	// 读取 [tensort] 配置项
	m_engine_path = ini->GetValue("tensort", "engine_path", "");
	m_engine_file = ini->GetValue("tensort", "engine_file", "car.transd.engine");
	std::string label_path = ini->GetValue("tensort", "label_path", "");
	m_label_file = ini->GetValue("tensort", "label_file", "label.txt");

	// 使用std::filesystem处理rknn的label_file路径
	ghc::filesystem::path engine_Path = ghc::filesystem::path(m_engine_path) / m_engine_file;
	m_engine_file = engine_Path.string();
	replace_all(m_engine_file, "\\", "/");

	// 使用std::filesystem处理label_file路径
	ghc::filesystem::path labelFilePath = ghc::filesystem::path(m_engine_path) / m_label_file;
	m_label_file = labelFilePath.string();
	// 替换路径中的反斜杠
	replace_all(m_label_file, "\\", "/");
	// 打开label文件并读取内容
	std::ifstream f(m_label_file);
	if (f.is_open())
	{
		std::string name;
		int i = 0;
		while (std::getline(f, name)) {
			m_maplabels[i++] = name;
		}
	}

	// 读取 [rknn] 配置项
	rknn_path = ini->GetValue("rknn", "rknn_path", "");
	rknn_file = ini->GetValue("rknn", "rknn_file", "");
	rknn_label_path = ini->GetValue("rknn", "label_path", "");
	rknn_label_file = ini->GetValue("rknn", "label_file", "");

	// 使用std::filesystem处理rknn的label_file路径
	ghc::filesystem::path rknnPath = ghc::filesystem::path(rknn_path) / rknn_file;
	rknn_file = rknnPath.string();
	replace_all(rknn_file, "\\", "/");

	// 使用std::filesystem处理rknn的label_file路径
	ghc::filesystem::path rknnLabelPath = ghc::filesystem::path(rknn_label_path) / rknn_label_file;
	rknn_label_file = rknnLabelPath.string();
	replace_all(rknn_label_file, "\\", "/");



	// 读取 [ffmpeg] 配置项
	m_encoder_name = ini->GetValue("ffmpeg", "encoder_name", "libx264");
	m_decoder_name = ini->GetValue("ffmpeg", "decoder_name", "libx264");
	m_nPush = ini->GetLongValue("ffmpeg", "use_push", 0);
	m_push_ip = ini->GetValue("ffmpeg", "push_ip", "127.0.0.1");
	m_push_port = ini->GetValue("ffmpeg", "push_port", "554");


}

// 各配置项的访问方法
int CGlobalManager::getOutWidth() const {
	return out_width;
}

int CGlobalManager::getOutHeight() const {
	return out_height;
}

int CGlobalManager::getSleeptime() const {
	return sleeptime;
}

std::string CGlobalManager::getYoloVersion() const {
	return yolo_version;
}

std::string CGlobalManager::getWeightsPath() const {
	return weights_path;
}

std::string CGlobalManager::getClassPath() const {
	return class_path;
}


std::string CGlobalManager::getEnginePath() const {
	return m_engine_path;
}
std::string CGlobalManager::getEngineFile() const {

	return m_engine_file;
}

std::string CGlobalManager::getClassFile() const {
	std::string file = class_path;
	if (!file.empty() && file.back() != '/') {
		file += '/';
	}
	file += class_file;
	std::replace(file.begin(), file.end(), '\\', '/');
	return file;
}

std::string CGlobalManager::getWeightsFile() const {
	std::string file = weights_path;
	if (!file.empty() && file.back() != '/') {
		file += '/';
	}
	file += weights_file;
	replace_all(file, "\\", "/");
	return file;
}


std::string CGlobalManager::getPushPath(std::string strTaskid) 
{
	char buffer[256]; // 假设最大长度不会超过 256，可根据需要调整大小
	std::snprintf(buffer, sizeof(buffer), "rtsp://%s:%s/Media/%s",
		m_push_ip.c_str(), m_push_port.c_str(), strTaskid.c_str());
	return std::string(buffer);
}

std::string CGlobalManager::getPushPath()
{
	char buffer[256]; // 假设最大长度不会超过 256，可根据需要调整大小
	std::snprintf(buffer, sizeof(buffer), "rtsp://%s:%s/Media/%s",
		m_push_ip.c_str(), m_push_port.c_str(), std::to_string(taskid).c_str());
	taskid++;
	return std::string(buffer);
}

std::string CGlobalManager::getEncoderName()
{
	return m_encoder_name;
}

std::string CGlobalManager::getDecoderName()
{
	return m_decoder_name;
}

bool CGlobalManager::getUsePush()
{
	if (m_nPush == 1)
	{
		return true;
	}
	else
	{
		return false;
	}

}

std::string CGlobalManager::getRknnFile() const
{
	return rknn_file;
}

std::string CGlobalManager::getRknnLabelFile() const
{
	return rknn_label_file;
}

std::map<int, std::string> CGlobalManager::getLabelMap() const
{
	return m_maplabels;
}
